home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj1191.zip / CPROG.ASC < prev    next >
Text File  |  1991-10-18  |  34KB  |  932 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4.  
  5.  
  6. [LISTING ONE]
  7.  
  8. /* ------------- normal.c ------------ */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <conio.h>
  14. #include <dos.h>
  15. #include "dflat.h"
  16.  
  17. #ifdef INCLUDE_MULTIDOCS
  18. static void near PaintOverLappers(WINDOW wnd);
  19. static void near PaintUnderLappers(WINDOW wnd);
  20. #endif
  21. static int InsideWindow(WINDOW, int, int);
  22. #ifdef INCLUDE_SYSTEM_MENUS
  23. static void TerminateMoveSize(void);
  24. static void SaveBorder(RECT);
  25. static void RestoreBorder(RECT);
  26. static RECT PositionIcon(WINDOW);
  27. static void near dragborder(WINDOW, int, int);
  28. static void near sizeborder(WINDOW, int, int);
  29. static int px = -1, py = -1;
  30. static int diff;
  31. static int conditioning;
  32. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc, {-1,-1,-1,-1}};
  33. static int *Bsave;
  34. static int Bht, Bwd;
  35. int WindowMoving;
  36. int WindowSizing;
  37. #endif
  38. /* -------- array of class definitions -------- */
  39. CLASSDEFS classdefs[] = {
  40.     #undef ClassDef
  41.     #define ClassDef(c,b,p,a) {b,p,a},
  42.     #include "classes.h"
  43. };
  44. WINDOW HiddenWindow;
  45.  
  46. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  47. {
  48.     int mx = (int) p1 - GetLeft(wnd);
  49.     int my = (int) p2 - GetTop(wnd);
  50.     int DoneClosing = FALSE;
  51.     switch (msg)    {
  52.         case CREATE_WINDOW:
  53.             AppendBuiltWindow(wnd);  /* add to the lists */
  54.             AppendFocusWindow(wnd);
  55. #ifdef INCLUDE_SCROLLBARS
  56.             if (!SendMessage(NULL, MOUSE_INSTALLED, 0, 0))
  57.                 ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  58. #endif
  59.             if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  60.                 GetVideoBuffer(wnd);
  61.             break;
  62.         case SHOW_WINDOW:
  63.             if ((GetParent(wnd) == NULL || isVisible(GetParent(wnd)))
  64. #ifdef INCLUDE_SYSTEM_MENUS
  65.                             && !conditioning
  66. #endif
  67.                                                     )    {
  68.                 WINDOW cwnd = Focus.FirstWindow;
  69.                 if (TestAttribute(wnd, SAVESELF) &&
  70.                                 wnd->videosave == NULL)
  71.                     GetVideoBuffer(wnd);
  72.                 SetVisible(wnd);
  73.                 SendMessage(wnd, PAINT, 0, 0);
  74.                 SendMessage(wnd, BORDER, 0, 0);
  75.                 /* --- show the children of this window --- */
  76.                 while (cwnd != NULL)    {
  77.                     if (GetParent(cwnd) == wnd &&
  78.                             cwnd->condition != ISCLOSING)
  79.                         SendMessage(cwnd, msg, p1, p2);
  80.                     cwnd = NextWindow(cwnd);
  81.                 }
  82.             }
  83.             break;
  84.         case HIDE_WINDOW:
  85.             if (isVisible(wnd)
  86. #ifdef INCLUDE_SYSTEM_MENUS
  87.                 && !conditioning
  88. #endif
  89.                                 )    {
  90.                 WINDOW cwnd = Focus.LastWindow;
  91.                 /* --- hide the children of this window --- */
  92.                 while (cwnd != NULL)    {
  93.                     if (GetParent(cwnd) == wnd)
  94.                         ClearVisible(cwnd);
  95.                     cwnd = PrevWindow(cwnd);
  96.                 }
  97.                 ClearVisible(wnd);
  98.                 /* --- paint what this window covered --- */
  99.                 if (wnd->videosave != NULL)
  100.                     RestoreVideoBuffer(wnd);
  101. #ifdef INCLUDE_MULTIDOCS
  102.                 else
  103.                     PaintOverLappers(wnd);
  104. #endif
  105.             }
  106.             break;
  107. #ifdef INCLUDE_HELP
  108.         case DISPLAY_HELP:
  109.             DisplayHelp(wnd, (char *)p1);
  110.             break;
  111. #endif
  112.         case INSIDE_WINDOW:
  113.             return InsideWindow(wnd, (int) p1, (int) p2);
  114.         case KEYBOARD:
  115. #ifdef INCLUDE_SYSTEM_MENUS
  116.             if (WindowMoving || WindowSizing)    {
  117.                 /* -- move or size a window with keyboard -- */
  118.                 int x, y;
  119.                 x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  120.                 y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  121.                 switch ((int)p1)    {
  122.                     case ESC:
  123.                         TerminateMoveSize();
  124.                         return TRUE;
  125.                     case UP:
  126.                         if (y)
  127.                             --y;
  128.                         break;
  129.                     case DN:
  130.                         if (y < SCREENHEIGHT-1)
  131.                             y++;
  132.                         break;
  133.                     case FWD:
  134.                         if (x < SCREENWIDTH-1)
  135.                             x++;
  136.                         break;
  137.                     case BS:
  138.                         if (x)
  139.                             --x;
  140.                         break;
  141.                     case '\r':
  142.                         SendMessage(wnd,BUTTON_RELEASED,x,y);
  143.                     default:
  144.                         return TRUE;
  145.                 }
  146.                 /* -- use the mouse functions to move/size - */
  147.                 SendMessage(wnd, MOUSE_CURSOR, x, y);
  148.                 SendMessage(wnd, MOUSE_MOVED, x, y);
  149.                 break;
  150.             }
  151. #endif
  152.             switch ((int)p1)    {
  153. #ifdef INCLUDE_HELP
  154.                 case F1:
  155.                     SendMessage(wnd, COMMAND, ID_HELP, 0);
  156.                     return TRUE;
  157. #endif
  158.                 case ALT_F6:
  159.                     SetNextFocus(inFocus);
  160.                     SkipSystemWindows(FALSE);
  161.                     return TRUE;
  162. #ifdef INCLUDE_SYSTEM_MENUS
  163.                 case ' ':
  164.                     if ((int)p2 & ALTKEY)
  165.                         if (TestAttribute(wnd, HASTITLEBAR))
  166.                             if (TestAttribute(wnd, CONTROLBOX))
  167.                                 BuildSystemMenu(wnd);
  168.                     return TRUE;
  169. #endif
  170.                 case CTRL_F4:
  171.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  172.                     SkipSystemWindows(FALSE);
  173.                     return TRUE;
  174.                 default:
  175.                     break;
  176.             }
  177.             /* ------- fall through ------- */
  178.         case ADDSTATUS:
  179.         case SHIFT_CHANGED:
  180.             if (GetParent(wnd) != NULL)
  181.                 PostMessage(GetParent(wnd), msg, p1, p2);
  182.             break;
  183.         case PAINT:
  184.             if (isVisible(wnd))    
  185.                 ClearWindow(wnd, (RECT *)p1, ' ');
  186.             break;
  187.         case BORDER:
  188.             if (isVisible(wnd))    {
  189.                 if (TestAttribute(wnd, HASBORDER))
  190.                     RepaintBorder(wnd, (RECT *)p1);
  191.                 else if (TestAttribute(wnd, HASTITLEBAR))
  192.                     DisplayTitle(wnd, (RECT *)p1);
  193.                 if (wnd->StatusBar != NULL)
  194.                     SendMessage(wnd->StatusBar, PAINT, p1, 0);
  195.             }
  196.             break;
  197. #ifdef INCLUDE_SYSTEM_MENUS
  198.         case COMMAND:
  199.             switch ((int)p1)    {
  200. #ifdef INCLUDE_HELP
  201.                 case ID_HELP:
  202.                     DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
  203.                     break;
  204. #endif
  205.                 case ID_SYSRESTORE:
  206.                     SendMessage(wnd, RESTORE, 0, 0);
  207.                     break;
  208.                 case ID_SYSMOVE:
  209.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  210.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  211.                     SendMessage(wnd, MOUSE_CURSOR, GetLeft(wnd), GetTop(wnd));
  212.                     WindowMoving = TRUE;
  213.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  214.                     break;
  215.                 case ID_SYSSIZE:
  216.                  SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  217.                  SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  218.                  SendMessage(wnd, MOUSE_CURSOR, GetRight(wnd), GetBottom(wnd));
  219.                  WindowSizing = TRUE;
  220.                  dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  221.                  break;
  222.                 case ID_SYSMINIMIZE:
  223.                     SendMessage(wnd, MINIMIZE, 0, 0);
  224.                     break;
  225.                 case ID_SYSMAXIMIZE:
  226.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  227.                     break;
  228.                 case ID_SYSCLOSE:
  229.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  230.                     break;
  231.                 default:
  232.                     break;
  233.             }
  234.             break;
  235. #endif
  236.         case SETFOCUS:
  237.             if (p1 && inFocus != wnd)    {
  238.                 WINDOW pwnd = GetParent(wnd);
  239.                 int Redraw = isVisible(wnd) &&
  240.                        !TestAttribute(wnd, SAVESELF);
  241.                 if (GetClass(pwnd) == APPLICATION)    {
  242.                     WINDOW cwnd = Focus.FirstWindow;
  243.                     /* -- if no children, do not need selective
  244.                         redraw --- */
  245.                     while (cwnd != NULL)    {
  246.                         if (GetParent(cwnd) == wnd)
  247.                             break;
  248.                         cwnd = NextWindow(cwnd);
  249.                     }
  250.                     if (cwnd == NULL)
  251.                         Redraw = FALSE;
  252.                 }
  253.                 /* ---- setting focus ------ */
  254.                 SendMessage(inFocus, SETFOCUS, FALSE, 0);
  255.  
  256.                 if (Redraw)
  257.                     PaintUnderLappers(wnd);
  258.  
  259.                 /* remove window from list */
  260.                 RemoveFocusWindow(wnd);
  261.                 /* move window to end of list */
  262.                 AppendFocusWindow(wnd);
  263.                 inFocus = wnd;
  264.  
  265.                 if (Redraw)
  266.                     SendMessage(wnd, BORDER, 0, 0);
  267.                 else    {
  268.                     if (pwnd == NULL ||
  269.                         GetClass(pwnd) == DIALOG ||
  270.                             DerivedClass(GetClass(pwnd)) ==
  271.                                 DIALOG || GetClass(pwnd) ==
  272.                                         APPLICATION)
  273.                         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  274.                     else
  275.                         SendMessage(pwnd, SHOW_WINDOW, 0, 0);
  276.                 }
  277.             }
  278.             else if (!p1 && inFocus == wnd)    {
  279.                 /* -------- clearing focus --------- */
  280.                 inFocus = NULL;
  281.                 SendMessage(wnd, BORDER, 0, 0);
  282.             }
  283.             break;
  284.         case DOUBLE_CLICK:
  285. #ifdef INCLUDE_SYSTEM_MENUS
  286.             if (!WindowSizing && !WindowMoving)
  287. #endif
  288.                 if (HitControlBox(wnd, mx, my))
  289.                     PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  290.             break;
  291.         case LEFT_BUTTON:
  292. #ifdef INCLUDE_SYSTEM_MENUS
  293.             if (WindowSizing || WindowMoving)
  294.                 break;
  295. #endif
  296.             if (HitControlBox(wnd, mx, my))    {
  297.                 BuildSystemMenu(wnd);
  298.                 break;
  299.             }
  300. #ifdef INCLUDE_SYSTEM_MENUS
  301.             if (my == 0 && mx > -1 && mx < WindowWidth(wnd))  {
  302.                 /* ---------- hit the top border -------- */
  303.                 if (TestAttribute(wnd, MINMAXBOX) &&
  304.                         TestAttribute(wnd, HASTITLEBAR))  {
  305.                     if (mx == WindowWidth(wnd)-2)    {
  306.                         if (wnd->condition == ISRESTORED)
  307.                             /* --- hit the maximize box --- */
  308.                             SendMessage(wnd, MAXIMIZE, 0, 0);
  309.                         else
  310.                             /* --- hit the restore box --- */
  311.                             SendMessage(wnd, RESTORE, 0, 0);
  312.                         break;
  313.                     }
  314.                     if (mx == WindowWidth(wnd)-3)    {
  315.                         /* --- hit the minimize box --- */
  316.                         if (wnd->condition != ISMINIMIZED)
  317.                             SendMessage(wnd, MINIMIZE, 0, 0);
  318.                         break;
  319.                     }
  320.                 }
  321.                 if (wnd->condition != ISMAXIMIZED &&
  322.                             TestAttribute(wnd, MOVEABLE))    {
  323.                     WindowMoving = TRUE;
  324.                     px = mx;
  325.                     py = my;
  326.                     diff = (int) mx;
  327.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  328.                         (PARAM) &dwnd);
  329.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  330.                 }
  331.                 break;
  332.             }
  333.             if (mx == WindowWidth(wnd)-1 &&
  334.                     my == WindowHeight(wnd)-1)    {
  335.                 /* ------- hit the resize corner ------- */
  336.                 if (wnd->condition == ISMINIMIZED ||
  337.                         !TestAttribute(wnd, SIZEABLE))
  338.                     break;
  339.                 if (wnd->condition == ISMAXIMIZED)    {
  340.                     if (TestAttribute(GetParent(wnd),HASBORDER))
  341.                         break;
  342.                     /* ----- resizing a maximized window over a
  343.                             borderless parent ----- */
  344.                     wnd = GetParent(wnd);
  345.                 }
  346.                 WindowSizing = TRUE;
  347.                 SendMessage(wnd, CAPTURE_MOUSE,
  348.                     TRUE, (PARAM) &dwnd);
  349.                 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  350.             }
  351. #endif
  352.             break;
  353. #ifdef INCLUDE_SYSTEM_MENUS
  354.         case MOUSE_MOVED:
  355.             if (WindowMoving)    {
  356.                 int leftmost = 0, topmost = 0,
  357.                     bottommost = SCREENHEIGHT-2,
  358.                     rightmost = SCREENWIDTH-2;
  359.                 int x = (int) p1 - diff;
  360.                 int y = (int) p2;
  361.                 if (GetParent(wnd) != NULL &&
  362.                         !TestAttribute(wnd, NOCLIP))    {
  363.                     WINDOW wnd1 = GetParent(wnd);
  364.                     topmost    = GetClientTop(wnd1);
  365.                     leftmost   = GetClientLeft(wnd1);
  366.                     bottommost = GetClientBottom(wnd1);
  367.                     rightmost  = GetClientRight(wnd1);
  368.                 }
  369.                 if (x < leftmost || x > rightmost ||
  370.                         y < topmost || y > bottommost)    {
  371.                     x = max(x, leftmost);
  372.                     x = min(x, rightmost);
  373.                     y = max(y, topmost);
  374.                     y = min(y, bottommost);
  375.                     SendMessage(NULL,MOUSE_CURSOR,x+diff,y);
  376.                 }
  377.                 if (x != px || y != py)    {
  378.                     px = x;
  379.                     py = y;
  380.                     dragborder(wnd, x, y);
  381.                 }
  382.                 return TRUE;
  383.             }
  384.             if (WindowSizing)    {
  385.                 sizeborder(wnd, (int) p1, (int) p2);
  386.                 return TRUE;
  387.             }
  388.             break;
  389.         case BUTTON_RELEASED:
  390.             if (WindowMoving || WindowSizing)    {
  391.                 if (WindowMoving)
  392.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  393.                 else
  394.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  395.                 TerminateMoveSize();
  396.             }
  397.             break;
  398.         case MAXIMIZE:
  399.             if (wnd->condition != ISMAXIMIZED)    {
  400.                 RECT rc = {0, 0, 0, 0};
  401.                 RECT holdrc;
  402.                 holdrc = wnd->RestoredRC;
  403.                 rc.rt = SCREENWIDTH-1;
  404.                 rc.bt = SCREENHEIGHT-1;
  405.                 if (GetParent(wnd))
  406.                     rc = ClientRect(GetParent(wnd));
  407.                 wnd->condition = ISMAXIMIZED;
  408.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  409.                 conditioning = TRUE;
  410.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  411.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  412.                 conditioning = FALSE;
  413.                 if (wnd->restored_attrib == 0)
  414.                     wnd->restored_attrib = wnd->attrib;
  415. #ifdef INCLUDE_SHADOWS
  416.                 ClearAttribute(wnd, SHADOW);
  417. #endif
  418.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  419.                 wnd->RestoredRC = holdrc;
  420.             }
  421.             break;
  422.         case MINIMIZE:
  423.             if (wnd->condition != ISMINIMIZED)    {
  424.                 RECT rc;
  425.                 RECT holdrc;
  426.  
  427.                 holdrc = wnd->RestoredRC;
  428.                 rc = PositionIcon(wnd);
  429.                 wnd->condition = ISMINIMIZED;
  430.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  431.                 conditioning = TRUE;
  432.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  433.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  434.                 SetPrevFocus(wnd);
  435.                 conditioning = FALSE;
  436.                 if (wnd->restored_attrib == 0)
  437.                     wnd->restored_attrib = wnd->attrib;
  438.                 ClearAttribute(wnd,
  439.                     SHADOW | SIZEABLE | HASMENUBAR |
  440.                     VSCROLLBAR | HSCROLLBAR);
  441.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  442.                 wnd->RestoredRC = holdrc;
  443.             }
  444.             break;
  445.         case RESTORE:
  446.             if (wnd->condition != ISRESTORED)    {
  447.                 RECT holdrc;
  448.                 holdrc = wnd->RestoredRC;
  449.                 wnd->condition = ISRESTORED;
  450.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  451.                 wnd->attrib = wnd->restored_attrib;
  452.                 wnd->restored_attrib = 0;
  453.                 conditioning = TRUE;
  454.                 SendMessage(wnd, MOVE, wnd->RestoredRC.lf, wnd->RestoredRC.tp);
  455.                 wnd->RestoredRC = holdrc;
  456.                 SendMessage(wnd, SIZE, wnd->RestoredRC.rt, wnd->RestoredRC.bt);
  457.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  458.                 conditioning = FALSE;
  459.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  460.             }
  461.             break;
  462.         case MOVE:    {
  463.             WINDOW wnd1 = Focus.FirstWindow;
  464.             int wasVisible = isVisible(wnd);
  465.             int xdif = (int) p1 - wnd->rc.lf;
  466.             int ydif = (int) p2 - wnd->rc.tp;
  467.  
  468.             if (xdif == 0 && ydif == 0)
  469.                 return FALSE;
  470.             if (wasVisible)
  471.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  472.             wnd->rc.lf = (int) p1;
  473.             wnd->rc.tp = (int) p2;
  474.             wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  475.             wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  476.             if (wnd->condition == ISRESTORED)
  477.                 wnd->RestoredRC = wnd->rc;
  478.             while (wnd1 != NULL)    {
  479.                 if (GetParent(wnd1) == wnd)
  480.                   SendMessage(wnd1, MOVE, wnd1->rc.lf+xdif, wnd1->rc.tp+ydif);
  481.                 wnd1 = NextWindow(wnd1);
  482.             }
  483.             if (wasVisible)
  484.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  485.             break;
  486.         }
  487.         case SIZE:    {
  488.             int wasVisible = isVisible(wnd);
  489.             WINDOW wnd1 = Focus.FirstWindow;
  490.             RECT rc;
  491.             int xdif = (int) p1 - wnd->rc.rt;
  492.             int ydif = (int) p2 - wnd->rc.bt;
  493.  
  494.             if (xdif == 0 && ydif == 0)
  495.                 return FALSE;
  496.             if (wasVisible)
  497.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  498.             wnd->rc.rt = (int) p1;
  499.             wnd->rc.bt = (int) p2;
  500.             wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  501.             wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  502.  
  503.             if (wnd->condition == ISRESTORED)
  504.                 wnd->RestoredRC = WindowRect(wnd);
  505.  
  506.             rc = ClientRect(wnd);
  507.             while (wnd1 != NULL)    {
  508.                 if (GetParent(wnd1) == wnd &&
  509.                         wnd1->condition == ISMAXIMIZED)
  510.                     SendMessage(wnd1, SIZE, RectRight(rc), RectBottom(rc));
  511.                 wnd1 = NextWindow(wnd1);
  512.             }
  513.  
  514.             if (wasVisible)
  515.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  516.             break;
  517.         }
  518. #endif
  519.         case CLOSE_WINDOW:
  520.             wnd->condition = ISCLOSING;
  521.             if (wnd->PrevMouse != NULL)
  522.                 SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  523.             if (wnd->PrevKeyboard != NULL)
  524.                 SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  525.             /* ----------- hide this window ------------ */
  526.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  527.             /* --- close the children of this window --- */
  528.             while (!DoneClosing)    {
  529.                 WINDOW wnd1 = Focus.LastWindow;
  530.                 DoneClosing = TRUE;
  531.                 while (wnd1 != NULL)    {
  532.                     WINDOW prwnd = PrevWindow(wnd1);
  533.                     if (GetParent(wnd1) == wnd)    {
  534.                         if (inFocus == wnd1)    {
  535.                             RemoveFocusWindow(wnd);
  536.                             AppendFocusWindow(wnd);
  537.                             inFocus = wnd;
  538.                         }
  539.                         SendMessage(wnd1,CLOSE_WINDOW,0,0);
  540.                         DoneClosing = FALSE;
  541.                         break;
  542.                     }
  543.                     wnd1 = prwnd;
  544.                 }
  545.             }
  546.             /* --- change focus if this window had it -- */
  547.             SetPrevFocus(wnd);
  548.             /* ------- remove this window from the
  549.                     list of open windows ------------- */
  550.             RemoveBuiltWindow(wnd);
  551.             /* ------- remove this window from the
  552.                     list of in-focus windows ---------- */
  553.             RemoveFocusWindow(wnd);
  554.             /* -- free memory allocated to this window - */
  555.             if (wnd->title != NULL)
  556.                 free(wnd->title);
  557.             if (wnd->videosave != NULL)
  558.                 free(wnd->videosave);
  559.             free(wnd);
  560.             break;
  561.         default:
  562.             break;
  563.     }
  564.     return TRUE;
  565. }
  566. /* ---- compute lower left icon space in a rectangle ---- */
  567. #ifdef INCLUDE_SYSTEM_MENUS
  568. static RECT LowerRight(RECT prc)
  569. {
  570.     RECT rc;
  571.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  572.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  573.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  574.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  575.     return rc;
  576. }
  577. /* ----- compute a position for a minimized window icon ---- */
  578. static RECT PositionIcon(WINDOW wnd)
  579. {
  580.     RECT rc;
  581.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  582.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  583.     RectRight(rc) = SCREENWIDTH-1;
  584.     RectBottom(rc) = SCREENHEIGHT-1;
  585.     if (GetParent(wnd))    {
  586.         WINDOW wnd1 = (WINDOW) -1;
  587.         RECT prc;
  588.         prc = WindowRect(GetParent(wnd));
  589.         rc = LowerRight(prc);
  590.         /* - search for icon available location - */
  591.         while (wnd1 != NULL)    {
  592.             wnd1 = GetFirstChild(GetParent(wnd));
  593.             while (wnd1 != NULL)    {
  594.                 if (wnd1->condition == ISMINIMIZED)    {
  595.                     RECT rc1;
  596.                     rc1 = WindowRect(wnd1);
  597.                     if (RectLeft(rc1) == RectLeft(rc) &&
  598.                             RectTop(rc1) == RectTop(rc))    {
  599.                         RectLeft(rc) -= ICONWIDTH;
  600.                         RectRight(rc) -= ICONWIDTH;
  601.                         if (RectLeft(rc) < RectLeft(prc)+1)   {
  602.                             RectLeft(rc) =
  603.                                 RectRight(prc)-ICONWIDTH;
  604.                             RectRight(rc) =
  605.                                 RectLeft(rc)+ICONWIDTH-1;
  606.                             RectTop(rc) -= ICONHEIGHT;
  607.                             RectBottom(rc) -= ICONHEIGHT;
  608.                             if (RectTop(rc) < RectTop(prc)+1)
  609.                                 return LowerRight(prc);
  610.                         }
  611.                         break;
  612.                     }
  613.                 }
  614.                 wnd1 = GetNextChild(GetParent(wnd), wnd1);
  615.             }
  616.         }
  617.     }
  618.     return rc;
  619. }
  620. /* ----- terminate the move or size operation ----- */
  621. static void TerminateMoveSize(void)
  622. {
  623.     px = py = -1;
  624.     diff = 0;
  625.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  626.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  627.     RestoreBorder(dwnd.rc);
  628.     WindowMoving = WindowSizing = FALSE;
  629. }
  630. /* ---- build a dummy window border for moving or sizing --- */
  631. static void near dragborder(WINDOW wnd, int x, int y)
  632. {
  633.     RestoreBorder(dwnd.rc);
  634.     /* ------- build the dummy window -------- */
  635.     dwnd.rc.lf = x;
  636.     dwnd.rc.tp = y;
  637.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  638.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  639.     dwnd.ht = WindowHeight(wnd);
  640.     dwnd.wd = WindowWidth(wnd);
  641.     dwnd.parent = GetParent(wnd);
  642.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  643.     InitWindowColors(&dwnd);
  644.     SaveBorder(dwnd.rc);
  645.     RepaintBorder(&dwnd, NULL);
  646. }
  647. /* ---- write the dummy window border for sizing ---- */
  648. static void near sizeborder(WINDOW wnd, int rt, int bt)
  649. {
  650.     int leftmost = GetLeft(wnd)+10;
  651.     int topmost = GetTop(wnd)+3;
  652.     int bottommost = SCREENHEIGHT-1;
  653.     int rightmost  = SCREENWIDTH-1;
  654.     if (GetParent(wnd))    {
  655.         bottommost = min(bottommost, GetClientBottom(GetParent(wnd)));
  656.         rightmost  = min(rightmost, GetClientRight(GetParent(wnd)));
  657.     }
  658.     rt = min(rt, rightmost);
  659.     bt = min(bt, bottommost);
  660.     rt = max(rt, leftmost);
  661.     bt = max(bt, topmost);
  662.     SendMessage(NULL, MOUSE_CURSOR, rt, bt);
  663.  
  664.     if (rt != px || bt != py)
  665.         RestoreBorder(dwnd.rc);
  666.  
  667.     /* ------- change the dummy window -------- */
  668.     dwnd.ht = bt-dwnd.rc.tp+1;
  669.     dwnd.wd = rt-dwnd.rc.lf+1;
  670.     dwnd.rc.rt = rt;
  671.     dwnd.rc.bt = bt;
  672.     if (rt != px || bt != py)    {
  673.         px = rt;
  674.         py = bt;
  675.         SaveBorder(dwnd.rc);
  676.         RepaintBorder(&dwnd, NULL);
  677.     }
  678. }
  679. #endif
  680. /* ----- adjust a rectangle to include the shadow ----- */
  681. #ifdef INCLUDE_SHADOWS
  682. static RECT adjShadow(WINDOW wnd)
  683. {
  684.     RECT rc;
  685.     rc = wnd->rc;
  686.     if (TestAttribute(wnd, SHADOW))    {
  687.         if (RectRight(rc) < SCREENWIDTH-1)
  688.             RectRight(rc)++;           
  689.         if (RectBottom(rc) < SCREENHEIGHT-1)
  690.             RectBottom(rc)++;
  691.     }
  692.     return rc;
  693. }
  694. #endif
  695. /* --- repaint a rectangular subsection of a window --- */
  696. #ifdef INCLUDE_MULTIDOCS
  697. static void near PaintOverLap(WINDOW wnd, RECT rc)
  698. {
  699.     int isBorder, isTitle, isData;
  700.     isBorder = isTitle = FALSE;
  701.     isData = TRUE;
  702.     if (TestAttribute(wnd, HASBORDER))    {
  703.         isBorder =  RectLeft(rc) == 0 &&
  704.                     RectTop(rc) < WindowHeight(wnd);
  705.         isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  706.                     RectRight(rc) >= WindowWidth(wnd)-1 &&
  707.                     RectTop(rc) < WindowHeight(wnd);
  708.         isBorder |= RectTop(rc) == 0 &&
  709.                     RectLeft(rc) < WindowWidth(wnd);
  710.         isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  711.                     RectBottom(rc) >= WindowHeight(wnd)-1 &&
  712.                     RectLeft(rc) < WindowWidth(wnd);
  713.     }
  714.     else if (TestAttribute(wnd, HASTITLEBAR))
  715.         isTitle = RectTop(rc) == 0 &&
  716.                   RectLeft(rc) > 0 &&
  717.                   RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  718.  
  719.     if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  720.         isData = FALSE;
  721.     if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
  722.         isData = FALSE;
  723.     if (TestAttribute(wnd, HASBORDER))    {
  724.         if (RectRight(rc) == 0)
  725.             isData = FALSE;
  726.         if (RectBottom(rc) == 0)
  727.             isData = FALSE;
  728.     }
  729. #ifdef INCLUDE_SHADOWS
  730.     if (TestAttribute(wnd, SHADOW))
  731.         isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  732.                     RectBottom(rc) == WindowHeight(wnd);
  733. #endif
  734.     if (isData)
  735.         SendMessage(wnd, PAINT, (PARAM) &rc, 0);
  736.     if (isBorder)
  737.         SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  738.     else if (isTitle)
  739.         DisplayTitle(wnd, &rc);
  740. }
  741. /* ------ paint the part of a window that is overlapped
  742.             by another window that is being hidden ------- */
  743. static void PaintOver(WINDOW wnd)
  744. {
  745.         RECT wrc, rc;
  746. #ifdef INCLUDE_SHADOWS
  747.         wrc = adjShadow(HiddenWindow);
  748.         rc = adjShadow(wnd);
  749. #else
  750.         wrc = HiddenWindow->rc;
  751.         rc = wnd->rc;
  752. #endif
  753.         rc = subRectangle(rc, wrc);
  754.         if (ValidRect(rc))
  755.             PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  756. }
  757. /* --- paint the overlapped parts of all children --- */
  758. static void PaintOverChildren(WINDOW pwnd)
  759. {
  760.     WINDOW cwnd = GetFirstFocusChild(pwnd);
  761.     while (cwnd != NULL)    {
  762.         if (cwnd != HiddenWindow)    {
  763.             PaintOver(cwnd);
  764.             PaintOverChildren(cwnd);
  765.         }
  766.         cwnd = GetNextFocusChild(pwnd, cwnd);
  767.     }
  768. }
  769. /* -- recursive overlapping paint of parents -- */
  770. static void PaintOverParents(WINDOW wnd)
  771. {
  772.     WINDOW pwnd = GetParent(wnd);
  773.     if (pwnd != NULL)    {
  774.         PaintOverParents(pwnd);
  775.         PaintOver(pwnd);
  776.         PaintOverChildren(pwnd);
  777.     }
  778. }
  779. /* - paint the parts of all windows that a window is over - */
  780. static void near PaintOverLappers(WINDOW wnd)
  781. {
  782.     HiddenWindow = wnd;
  783.     PaintOverParents(wnd);
  784. }
  785. /* --- paint those parts of a window that are overlapped --- */
  786. static void near PaintUnder(WINDOW wnd)
  787. {
  788.     WINDOW hwnd = Focus.FirstWindow;
  789.     while (hwnd != NULL)    {
  790.         /* ---- don't bother testing self ----- */
  791.         if (hwnd != wnd)    {
  792.             /* --- see if other window is descendent --- */
  793.             WINDOW pwnd = GetParent(hwnd);
  794.             while (pwnd != NULL)    {
  795.                 if (pwnd == wnd)
  796.                     break;
  797.                 pwnd = GetParent(pwnd);
  798.             }
  799.             /* ----- don't test descendent overlaps ----- */
  800.             if (pwnd == NULL)    {
  801.                 /* -- see if other window is ancestor --- */
  802.                 pwnd = GetParent(wnd);
  803.                 while (pwnd != NULL)    {
  804.                     if (pwnd == hwnd)
  805.                         break;
  806.                     pwnd = GetParent(pwnd);
  807.                 }
  808.                 /* --- don't test ancestor overlaps --- */
  809.                 if (pwnd == NULL)    {
  810.                     /* ---- other window must be ahead in
  811.                         focus chain ----- */
  812.                     WINDOW fwnd = NextWindow(wnd);
  813.                     while (fwnd != NULL)    {
  814.                         if (fwnd == hwnd)
  815.                             break;
  816.                         fwnd = NextWindow(fwnd);
  817.                     }
  818.                     if (fwnd != NULL)    {
  819.                         HiddenWindow = hwnd;
  820.                         PaintOver(wnd);
  821.                     }
  822.                 }
  823.             }
  824.         }
  825.         hwnd = NextWindow(hwnd);
  826.     }
  827.     /* --------- repaint all children of this window
  828.         the same way ----------- */
  829.     hwnd = Focus.FirstWindow;
  830.     while (hwnd != NULL)    {
  831.         if (GetParent(hwnd) == wnd)
  832.             PaintUnder(hwnd);
  833.         hwnd = NextWindow(hwnd);
  834.     }
  835. }
  836. /* paint the parts of a window that are under other windows */
  837. static void near PaintUnderLappers(WINDOW wnd)
  838. {
  839.     WINDOW pwnd = wnd;
  840.     /* find oldest ancestor younger than application window */
  841.     while (pwnd != NULL && GetClass(pwnd) != APPLICATION) {
  842.         if (TestAttribute(wnd, SAVESELF))
  843.             break;
  844.         wnd = pwnd;
  845.         pwnd = GetParent(pwnd);
  846.     }
  847.     PaintUnder(wnd);
  848. }
  849. #endif
  850. #ifdef INCLUDE_SYSTEM_MENUS
  851. /* --- save video area to be used by dummy window border --- */
  852. static void SaveBorder(RECT rc)
  853. {
  854.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  855.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  856.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  857.         RECT lrc;
  858.         int i;
  859.         int *cp;
  860.  
  861.         lrc = rc;
  862.         RectBottom(lrc) = RectTop(lrc);
  863.         getvideo(lrc, Bsave);
  864.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  865.         getvideo(lrc, Bsave + Bwd);
  866.         cp = Bsave + Bwd * 2;
  867.         for (i = 1; i < Bht-1; i++)    {
  868.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  869.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  870.         }
  871.     }
  872. }
  873. /* ---- restore video area used by dummy window border ---- */
  874. static void RestoreBorder(RECT rc)
  875. {
  876.     if (Bsave != NULL)    {
  877.         RECT lrc;
  878.         int i;
  879.         int *cp;
  880.         lrc = rc;
  881.         RectBottom(lrc) = RectTop(lrc);
  882.         storevideo(lrc, Bsave);
  883.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  884.         storevideo(lrc, Bsave + Bwd);
  885.         cp = Bsave + Bwd * 2;
  886.         for (i = 1; i < Bht-1; i++)    {
  887.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  888.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  889.         }
  890.         free(Bsave);
  891.         Bsave = NULL;
  892.     }
  893. }
  894. #endif
  895. /* ----- test if screen coordinates are in a window ---- */
  896. static int InsideWindow(WINDOW wnd, int x, int y)
  897. {
  898.     RECT rc;
  899.     rc = WindowRect(wnd);
  900.     if (!TestAttribute(wnd, NOCLIP))    {
  901.         WINDOW pwnd = GetParent(wnd);
  902.         while (pwnd != NULL)    {
  903.             rc = subRectangle(rc, ClientRect(pwnd));
  904.             pwnd = GetParent(pwnd);
  905.         }
  906.     }
  907.     return InsideRect(x, y, rc);
  908. }
  909. /* ----- find window that screen coordinates are in --- */
  910. WINDOW inWindow(int x, int y)
  911. {
  912.     WINDOW wnd = Focus.LastWindow;
  913.     while (wnd != NULL)    {
  914.         if (SendMessage(wnd, INSIDE_WINDOW, x, y))    {
  915.             WINDOW wnd1 = GetLastChild(wnd);
  916.             while (wnd1 != NULL)    {
  917.                 if (SendMessage(wnd1, INSIDE_WINDOW, x, y)) {
  918.                     if (isVisible(wnd))  {
  919.                         wnd = wnd1;
  920.                         break;
  921.                     }
  922.                 }
  923.                 wnd1 = GetPrevChild(wnd, wnd1);
  924.             }
  925.             break;
  926.         }
  927.         wnd = PrevWindow(wnd);
  928.     }
  929.     return wnd;
  930. }
  931.  
  932.